package com.yuyaogc.lowcode.engine.loader;

import com.google.common.graph.GraphBuilder;
import com.google.common.graph.Graphs;
import com.google.common.graph.MutableGraph;
import com.google.common.graph.Traverser;
import com.yuyaogc.lowcode.engine.entity.Module;
import com.yuyaogc.lowcode.engine.exception.EngineException;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.stream.Collectors;

public class Graph {
    public static Logger logger = LoggerFactory.getLogger(Graph.class);
    public static void check(List<Module> apps){
        List<String> appNames = apps.stream().map(a -> a.getName()).collect(Collectors.toList());
        MutableGraph<String> graph = GraphBuilder.directed().allowsSelfLoops(true).build();
        Set<String> missingApps = new HashSet<>();

        for(Module app: apps){
            String appName = String.format("%s.%s", app.getName(), app.getVersion());
            String[] dependencies = app.getDependencies();
            if (dependencies == null || dependencies.length == 0) {
                graph.addNode(appName);
            } else {
                for (String dependency : dependencies) {
                    String dependencyTag = StringUtils.substringAfterLast(dependency, ":");
                    if (StringUtils.isBlank(dependencyTag)) {
                        dependencyTag = "master";
                    }
                    dependencyTag = String.format("%s.%s", dependency, dependencyTag);
                    graph.putEdge(appName, dependencyTag);
                    if (!appNames.contains(dependency)) {
                        missingApps.add(appName + "依赖:" + dependencyTag);
                    }
                }
            }
        }

        if (missingApps.size() > 0) {
            logger.error(String.format("找不到依赖:%s 模组 %s", missingApps , appNames));
            throw new EngineException(String.format("找不到依赖:%s 模组 %s", missingApps , appNames));
        }

        if (Graphs.hasCycle(graph)) {
            logger.error(String.format("检测到循环依赖:%s", graph.edges()));
            throw new EngineException(String.format("检测到循环依赖:%s", graph.edges()));
        };

    }

    public static void main(String[] args) {
        MutableGraph<Long> graph2 = GraphBuilder.directed().allowsSelfLoops(true).build();
        graph2.putEdge(1l, 2l);
        graph2.putEdge(2l, 3l);
        graph2.putEdge(1l, 4l);
        graph2.putEdge(4l, 5l);
        graph2.putEdge(4l, 6l);

        System.out.println("Successors: " + graph2.successors(4l));
        System.out.println("predecessors: " + graph2.predecessors(3l));
        Iterator iterator = Traverser.forGraph(graph2).depthFirstPreOrder(1l).iterator();
        System.out.print("TopologicalSort: "  );
        while (iterator.hasNext()){
            System.out.print(iterator.next());
        }
        System.out.println(" "  );
    }
}
